<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
	<meta http-equiv="pragma" content="no-cache" />
    <meta name="author" content="Jayli" />
	<meta name="keywords" content="淘宝UED 前端工程师 拔赤" />	
	<meta name="description" content="淘宝前端工程师拔赤，关注尖端前端技术，关注yui" />
	<meta http-equiv="imagetoolbar" content="no" />
	<meta name="title" content="拔赤的文章列表" />
    <title>基于YUI3的组件开发</title>
    <link href="http://jayli.github.com/blog/atom.xml" rel="alternate" title="setImpl" type="application/atom+xml" />
    <link rel="stylesheet" href="http://jayli.github.com/blog/media/css/style.css">
    <link rel="stylesheet" href="http://jayli.github.com/blog/media/css/github.css">
	<style>
	</style>
    <script type="text/javascript" src="http://jayli.github.com/blog/media/js/highlight.pack.js"></script>
    <script type="text/javascript">
      hljs.initHighlightingOnLoad();
    </script>
	<!--[if lte IE 8]>
	<script src="http://a.tbcdn.cn/apps/lottery/00023/index-v3/js/html5.js"></script>
	<![endif]-->
	<meta name="baidu-tc-verification" content="afb6c9df553ef3493d9ee65263df0d55" />
	<script src="http://siteapp.baidu.com/static/webappservice/uaredirect.js" type="text/javascript"></script><script type="text/javascript">uaredirect("http://m.zoojs.org", "http://jayli.github.com/blog");</script>
  </head>
  <body>
    <div id="container">
      <div id="main" role="main">
        <header>
        <h1>基于YUI3的组件开发</h1>
        </header>
        <nav>
        <span><a title="home page" class="" href="/blog/index.html">home</a></span>
        <span><a title="tags" class="" href="/blog/tags.html">tags</a></span>
        <span><a title="about" class="" href="/blog/about.html">about me</a></span>
        <span><a title="flickr" class="" href="http://www.flickr.com/photos/lijing00333">flickr</a></span>
        <span><a title="blogroll" class="" href="/blog/links.html">links</a></span>
        <span><a title="projects" class="" href="/blog/projects.html">projects</a></span>
        <span><a title="subscribe me" class="" href="/blog/atom.xml">feed</a></span>
        </nav>
        <article class="content">
        <section class="post">
<blockquote><p>导语：如今的前端开发越来越OO，也越来越注重重用，娴熟的用js写出OO的前端代码已然是一个前端工程师的基本素质之一。与此同时，网站的开发过程也越来越类似于堆积木。模块思想也逐渐深入的应用在大型网站的开发之中，指导网站的设计和架构，在今天【珍珠奶茶帮】的分享中，我们来对基于YUI的组件开发做深入探讨。</p></blockquote>

<p>模块化的前端开发</p>

<p>在web技术迅猛发展的今天，大型网站的前端开发越来越依赖复杂的团队配合，而模块化思想则能有效的指导团队开发的效率提升和成本压缩。它使得我们在项目中将注意力放在颗粒化组件的组装上来，而不用花费精力去考究每个组件黑盒内的实现，从而使得项目开发更加高效。类似于某些软件的界面开发，无非是用鼠标将控件库中的控件拖拽到面板中摆一摆罢了。而在YUI2.x的时代，YUI中的大量组件也极大的方便了我们的开发，而如今YUI3具有更加强劲的动力，但还未有太多widget可用，则需要我们手动开发组件。</p>

<p>组件的特点是高内聚低耦合，且一个完整成熟的组件不应当依赖于环境，这和插件有着本质区别。因为组件只需要对外暴露接口，共外界调用即可。</p>

<p>此外，组件有一些必要的组成部分:组件需要初始化、组件有其依赖的字组件、库和皮肤。组件也可被修改（也被称作重新初始化）。再进一步看，本质上，组件都包含样式、独立的数据和交互逻辑，这三部分也被称作M(Module)、V(View)、C(Control)。比如在淘宝杂志中的评论组件，MVC是如此分布的：
组件中的MVC</p>

<p>其中Module和View应当完全剥离，他们通过Control连接起来。而且从他们各自的稳定性角度来讲，Module(data)是在运行时才能确定的，View(UI)是半确定的，因为可以换肤，而初始化的时候则必须有确定的皮肤，Controller(逻辑)则是确定的，包括数据格式和交互行为。这里很清楚的表明了组件的三个部分，如果一个组件的功能不好抽象，则可以按照这个思路进行抽象。
设计一个组件
组件设计者应当熟知：组件源于项目而高于项目，不要对组件的使用环境进行假设，设计之初将精力放在丰富的接口和参数配置上，同时，要设计出完善的黑盒交互。按照这个原则设计的组件具有可重用、易用、健壮的特点。</p>

<p>对于开发者来讲，要想保证前文提到的可重用、易用和健壮性，则需要遵循如下三个原则</p>

<ul>
<li>注意配置项的优先级</li>
<li>尽可能少的类</li>
<li>保证源码可扩展性。</li>
</ul>


<p>其中基础配置是指应当在具体项目中确定下来的配置，比如弹出框的行为，包括有无阴影、是否可拖拽、是否跟随滚动条滚动而滚动，项目中所有的弹框的这些属性应当统一，这些配置我们称为基础配置。缺省配置是指参数默认为空的时候的填补。必填的配置是强制传入的参数。</p>

<p>要使用尽可能少的类是为了保证代码的结构简单内聚，比如，我推荐使用原型单体来做源码的包装。而且在开发组件的时候，一定要区分最重要的两个方法，init和render，分别代表初始化和重新初始化，如果你的组件是可以被中途改变状态的，应当注意这一点。</p>

<p>另外，还有一些要诀是需要铭记在心的，这些要诀对于组件代码的可扩展性是很有帮助的。因为组件的生命周期很长，甚至要长过项目本身，这也意味着他的维护周期也很长，可能会有很多人不断的为这个组件增加功能，那么，做好组件的骨架以便后续的增量开发不增加源码的熵值则显得尤为重要，因此，能否搭建良好可扩展的组件结构也是体现开发者基本功的参照之一。这些要诀大致包括：</p>

<ul>
<li>属性属于对象、方法属于原型，</li>
<li>基于原型的(显式)构造器，</li>
<li>组件的自定义。</li>
</ul>


<p>其中第一点是常识，但工程师在做类继承的时候往往忽略了这个简单的原则，导致代码组织混乱。第二点的灵感是来自dojo、mootools、 prototype等框架在类继承方面的设计经验和良好实践，第三点的灵感则来自于YUI3关于OO的设计思想。</p>

<p>熟练运用以上原则对于开发一个高质量可扩展的组件是大有裨益的。最后总结下组件的一生，组件来源于特定项目和具体的业务场景，开发者将通用功能提取出来，形成组件原型，并被更多的项目和业务场景使用，同时其功能随着时间的推移而增加，组件变的越来越完善，它的生命周期远超过某个产品的生命周期，因此，我们有理由高喊我们的口号：产品恒久远，组件永流传。</p>

<p>ps：ok，说了这么多，还没有提到正题，这些和YUI有什么关系？确切说是和YUI3有什么关系？YUI3脱胎于YUI2，可以说青出于蓝而胜于蓝，YUI3天然优良的架构为组件的骨架搭建创建良好的基础，这些内容包含自定义事件、YUI3 教科书式的代码重用实践、以及其插件机制，由于时间关系，这些内容将在下期【珍珠奶茶会】上做分享，请密切关注。</p>

<p>本期分享的ppt：</p>

<p>http://www.slideshare.net/lijing00333/yui3-2728729</p>

<p>下期分享的ppt草稿抢先看：</p>

<p>http://www.slideshare.net/lijing00333/yui3-2563104</p>

</section>
<section class="meta">

<!--span class="tags">
  tagged by 
  
</span-->

<span class="time">
  posted at <time datetime="2010-07-01">2010-07-01</time>
</span>
</section>

<section class="comment">
<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'jayliblog'; // required: replace example with your forum shortname
	var disqus_identifier = 'urn:uuid:861eac1a-8cb6-4f3a-9287-870849446b4a';

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
</section>


        </article>
      </div>
    </div> <!--! end of #container -->
  </body>
</html>
